﻿using System.Net.WebSockets;
using FireChat.Share.HTTP.Model;
using FireChat.Share.Logger;
using FireChat.Server.Database.Manager;
using FireChat.Share.Web.Package;
using FireChat.Share.Web.Util;

namespace FireChat.Server.Session.Remote;


/// <summary>
/// FireChat 远程客户端
/// </summary>
public class RemoteSession
{
    /// <summary>
    /// WebSock核心
    /// </summary>
    private readonly HttpListenerWebSocketContext _context;


    /// <summary>
    /// 远程地址
    /// </summary>
    public Uri RequestUri => _context.RequestUri;

    /// <summary>
    /// 接收到数据包事件
    /// </summary>
    public event Action<ClientPackage>? PackageReceived;

    /// <summary>
    /// 是否已经关闭
    /// </summary>
    public bool IsClosed => _context.WebSocket.State is WebSocketState.Closed or WebSocketState.Aborted;

    /// <summary>
    /// 用户会话令牌
    /// </summary>
    public AccountToken AccountToken { get; set; } = AccountToken.None;

    /// <summary>
    /// 关闭中事件
    /// </summary>
    public event Action? Closing;



    /// <summary>
    /// 初始化远程客户端
    /// </summary>
    public RemoteSession(HttpListenerWebSocketContext context)
    {
        _context = context;
    }



    /// <summary>
    /// 开始接收消息
    /// </summary>
    public Task ReceiveAsync()
    {
        return _context.WebSocket.ReceivePackageAsync<ClientPackage>(
            package => PackageReceived?.Invoke(package),
            ex =>
            {
                if(ex is WebSocketException websocket_ex)
                {
                    $"客户端已断开连接 [{RequestUri}]".LogToConsole();
                    
                    this.DeleteAccountToken();
                    CloseAsync();
                    return false;
                }

                ex.LogToConsole();
                return true;
            });
    }

    /// <summary>
    /// 关闭远程连接
    /// </summary>
    public void CloseAsync()
    {
        Closing?.Invoke();
        _context.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
    }



    /// <summary>
    /// 发送一个数据包
    /// </summary>
    public Task SendAsync(ServerPackage package)
    {
        return _context.WebSocket.SendAsync(package);
    }
}
